{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "# import sys\n",
    "# sys.setrecursionlimit(10000)\n",
    "from time import time\n",
    "import numpy as np\n",
    "from Tree.tree_builder import tree_builder\n",
    "from Tree.tree_values import TreeValues\n",
    "from Tree.strategy_filling import strategy_filling\n",
    "from Tree.tree_visualizer import tree_visualizer\n",
    "from Tree.tree_cfr import TreeCFR\n",
    "from helper_classes import TreeParams, Node\n",
    "from Game.card_to_string_conversion import card_to_string\n",
    "from Game.card_tools import card_tools\n",
    "from Settings.constants import constants\n",
    "from Settings.arguments import arguments\n",
    "from Settings.game_settings import game_settings\n",
    "from Nn.value_nn import ValueNn\n",
    "from Nn.next_round_value import NextRoundValue\n",
    "from Nn.mock_nn_terminal import MockNnTerminal\n",
    "from TerminalEquity.terminal_equity import TerminalEquity\n",
    "from Training.train import Train\n",
    "from Tree.tree_strategy_filling import TreeStrategyFilling"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "PC = constants.players_count\n",
    "CC = game_settings.card_count\n",
    "P1 = constants.players.P1\n",
    "P2 = constants.players.P2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tree Build"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# params = TreeParams()\n",
    "# params.limit_to_street = True\n",
    "# first_node = Node()\n",
    "# first_node.board = np.zeros([], dtype=int)\n",
    "# first_node.street = 1\n",
    "# first_node.current_player = constants.players.P1\n",
    "# first_node.bets = np.array([arguments.ante, arguments.ante], dtype=int)\n",
    "# params.root_node = first_node\n",
    "# params.limit_to_street = True\n",
    "\n",
    "# root = tree_builder.build_tree(params)\n",
    "# strategy_filling.fill_uniform(root)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tree_visualizer.draw_tree(root, size='30,10', show_vars=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# params = TreeParams()\n",
    "# params.root_node = Node()\n",
    "# params.root_node.board = card_to_string.string_to_board('Ks')\n",
    "# params.root_node.street = 2\n",
    "# params.root_node.current_player = constants.players.P2\n",
    "# params.root_node.bets = np.array([300, 300])\n",
    "# params.limit_to_street = False\n",
    "# root = tree_builder.build_tree(params)\n",
    "# tree_visualizer.draw_tree(root, size='20,10')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exploitability"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# params = TreeParams()\n",
    "\n",
    "# params.root_node = Node()\n",
    "# params.root_node.board = card_to_string.string_to_board('')\n",
    "# params.root_node.street = 1\n",
    "# params.root_node.current_player = constants.players.P1\n",
    "# params.root_node.bets = np.array([100, 100])\n",
    "\n",
    "# tree = tree_builder.build_tree(params)\n",
    "\n",
    "# tree_values = TreeValues()\n",
    "\n",
    "# starting_ranges = np.zeros([PC,CC], dtype=arguments.dtype)\n",
    "# starting_ranges[0] = card_tools.get_uniform_range(params.root_node.board)\n",
    "# starting_ranges[1] = card_tools.get_uniform_range(params.root_node.board)\n",
    "\n",
    "# tree_values.compute_values(tree, starting_ranges)\n",
    "\n",
    "# print('Exploitability: ' + str(tree.exploitability) + ' [chips]' )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# CFR"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# params = TreeParams()\n",
    "\n",
    "# params.root_node = Node()\n",
    "# params.root_node.board = card_to_string.string_to_board('')\n",
    "# params.root_node.street = 1\n",
    "# params.root_node.current_player = constants.players.P1\n",
    "# params.root_node.bets = np.array([100, 100])\n",
    "\n",
    "# tree = tree_builder.build_tree(params)\n",
    "\n",
    "# starting_ranges = np.zeros([PC,CC], dtype=arguments.dtype)\n",
    "# starting_ranges[0] = card_tools.get_uniform_range(params.root_node.board)\n",
    "# starting_ranges[1] = card_tools.get_uniform_range(params.root_node.board)\n",
    "\n",
    "# t0 = time()\n",
    "# tree_cfr = TreeCFR()\n",
    "# %lprun -f tree_cfr.cfrs_iter_dfs tree_cfr.run_cfr(tree, starting_ranges)\n",
    "# print('Took time: {} for {} iters'.format(time()-t0, arguments.cfr_iters))\n",
    "\n",
    "# tree_values = TreeValues()\n",
    "# tree_values.compute_values(tree, starting_ranges)\n",
    "\n",
    "# print('Exploitability: ' + str(tree.exploitability) + ' [chips]' )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Card and Range Generator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# from DataGeneration.random_card_generator import card_generator\n",
    "# card_generator.generate_cards(6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# from DataGeneration.range_generator import RangeGenerator\n",
    "# r = RangeGenerator()\n",
    "# board = np.zeros([])\n",
    "# r.set_board(board)\n",
    "# BS,CC = 10,6\n",
    "# ranges = np.zeros([BS,CC])\n",
    "# r.generate_range(ranges)\n",
    "# print(np.array2string(ranges, suppress_small=True, precision=2))\n",
    "# print(np.array2string(np.sum(ranges, axis=1, keepdims=True), suppress_small=True, precision=2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Lookahead (test 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# params = TreeParams()\n",
    "# params.root_node = Node()\n",
    "# params.root_node.board = card_to_string.string_to_board('Ks')\n",
    "# params.root_node.street = 2\n",
    "# params.root_node.current_player = constants.players.P1\n",
    "# params.root_node.bets = np.array([100, 100])\n",
    "# params.limit_to_street = False\n",
    "# tree = tree_builder.build_tree(params)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "# from Tree.tree_strategy_filling import TreeStrategyFilling\n",
    "\n",
    "# filling = TreeStrategyFilling()\n",
    "\n",
    "# range1 = card_tools.get_uniform_range(params.root_node.board)\n",
    "# range2 = card_tools.get_uniform_range(params.root_node.board)\n",
    "\n",
    "# filling.fill_strategies(tree, P1, range1, range2)\n",
    "# filling.fill_strategies(tree, P2, range1, range2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# starting_ranges = np.zeros([PC,CC], dtype=arguments.dtype)\n",
    "# starting_ranges[0] = card_tools.get_uniform_range(params.root_node.board)\n",
    "# starting_ranges[1] = card_tools.get_uniform_range(params.root_node.board)\n",
    "\n",
    "# tree_values = TreeValues()\n",
    "# tree_values.compute_values(tree, starting_ranges)\n",
    "\n",
    "# print('Exploitability: ' + str(tree.exploitability) + ' [chips]' )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Next Round Value Bucketing test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "# next_round_value = NextRoundValue(None)\n",
    "# print(next_round_value._range_matrix)\n",
    "# # test of card to bucket range translation\n",
    "# range_ = np.arange(1,7).reshape([1,-1]).astype(float)\n",
    "# next_round_range = np.zeros([1, next_round_value.bucket_count * next_round_value.board_count], dtype=arguments.dtype)\n",
    "# next_round_value._card_range_to_bucket_range(range_, next_round_range)\n",
    "# print(next_round_range)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Next Round Value (mock test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # # test of get_value functionality\n",
    "# mock_nn = MockNnTerminal()\n",
    "# # mock_nn = ValueNn()\n",
    "# next_round_value = NextRoundValue(mock_nn)\n",
    "\n",
    "# # bets = np.array([100], dtype=float)\n",
    "# bets = np.array([1200], dtype=float)\n",
    "\n",
    "# next_round_value.start_computation(bets)\n",
    "\n",
    "# ranges = np.full([1,2,CC], 1/4, dtype=arguments.dtype)\n",
    "# values = np.zeros([1,2,CC], dtype=arguments.dtype)\n",
    "\n",
    "# np.random.seed(0)\n",
    "# ranges[0][0] = np.array([1,1,0,0,0,0])\n",
    "# ranges[0][1] = np.array([1,1,1,1,1,1])\n",
    "\n",
    "# next_round_value.get_value(ranges, values)\n",
    "\n",
    "# print(values)\n",
    "\n",
    "# ranges_2 = ranges.reshape([2,CC]).copy()\n",
    "# values_2 = np.full_like(ranges_2, -1)\n",
    "\n",
    "# terminal_equity = TerminalEquity()\n",
    "# terminal_equity.set_board(np.zeros([]))\n",
    "# terminal_equity.call_value(ranges_2, values_2)\n",
    "# print('terminal_equity')\n",
    "# print(values_2)\n",
    "\n",
    "# # output:\n",
    "# # [[[ 2.  2.  0.  0. -2. -2.]\n",
    "# #   [ 0.  0. -1. -1. -1. -1.]]]\n",
    "# # terminal_equity\n",
    "# # [[ 0.  0. -1. -1. -1. -1.]\n",
    "# #  [ 2.  2.  0.  0. -2. -2.]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# # needs to comment out some asserts and use_memory = True\n",
    "\n",
    "# board = card_to_string.string_to_board('Ks')\n",
    "\n",
    "# values_3 = np.full_like(values, -1)\n",
    "# next_round_value.get_value_on_board(board, values_3)\n",
    "\n",
    "# print(values_3)\n",
    "\n",
    "# # output:\n",
    "# # [[[ 0.2  0.2  0.   0.8 -0.6 -0.6]\n",
    "# #   [ 0.   0.   0.   1.  -1.  -1. ]]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Nn output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# data_dir = os.path.join(arguments.data_path, 'tfrecords')\n",
    "# T = Train(data_dir=data_dir)\n",
    "# T.train(num_epochs=100, verbose=0)\n",
    "# model = T.keras_model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "# npy_folder = r'C:\\Users\\domin\\Documents\\GitHub\\PyStack\\Data\\TrainSamples\\PotBet\\npy'\n",
    "# m = np.load(npy_folder + r'\\masks.0.npy')\n",
    "# x = np.load(npy_folder + r'\\inputs.0.npy')\n",
    "# y = np.load(npy_folder + r'\\targets.0.npy')\n",
    "\n",
    "# y_hat = model.predict(x)\n",
    "\n",
    "# temp = m[0]\n",
    "# m = np.zeros([72])\n",
    "# m[:36] = temp\n",
    "# m[36:] = temp\n",
    "# x = x[0]\n",
    "# y = y[0]\n",
    "# y_hat = y_hat[0]\n",
    "\n",
    "# d = np.dot(y_hat, x[:-1])\n",
    "# d /= 2\n",
    "# y_new = y_hat - d\n",
    "# y_new = y_hat\n",
    "\n",
    "# (y_new*m)[:36] - (y_new*m)[36:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Continual Re-solving in Tree"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "board = card_to_string.string_to_board('')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "params = TreeParams()\n",
    "params.root_node = Node()\n",
    "params.root_node.board = board\n",
    "params.root_node.street = 1\n",
    "params.root_node.current_player = constants.players.P1\n",
    "params.root_node.bets = np.array([300, 300])\n",
    "params.limit_to_street = False\n",
    "tree = tree_builder.build_tree(params)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\domin\\Documents\\GitHub\\PyStack\\Lookahead\\lookahead.py:348: RuntimeWarning: invalid value encountered in true_divide\n",
      "  out.children_cfvs /= scaler\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(3, 2, 6)\n",
      "(2, 2, 6)\n",
      "(2, 2, 6)\n",
      "(2, 2, 6)\n",
      "(2, 2, 6)\n",
      "(2, 2, 6)\n",
      "(2, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n",
      "(1, 2, 6)\n"
     ]
    }
   ],
   "source": [
    "filling = TreeStrategyFilling()\n",
    "\n",
    "range1 = card_tools.get_uniform_range(board)\n",
    "range2 = card_tools.get_uniform_range(board)\n",
    "\n",
    "filling.fill_strategies(tree, P1, range1, range2)\n",
    "filling.fill_strategies(tree, P2, range1, range2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Exploitability: 41.233696 [chips]\n"
     ]
    }
   ],
   "source": [
    "starting_ranges = np.zeros([PC,CC], dtype=arguments.dtype)\n",
    "starting_ranges[0] = card_tools.get_uniform_range(params.root_node.board)\n",
    "starting_ranges[1] = card_tools.get_uniform_range(params.root_node.board)\n",
    "\n",
    "tree_values = TreeValues()\n",
    "tree_values.compute_values(tree, starting_ranges)\n",
    "\n",
    "print('Exploitability: ' + str(tree.exploitability) + ' [chips]' )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "# tree_visualizer.draw_tree(tree, size='20,10')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "tensorflow",
   "language": "python",
   "name": "tensorflow"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
